package com.stx.jeepay.payment.controller.division;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.stx.jeepay.core.ctrls.AbstractCtrl;
import com.stx.jeepay.core.entity.PayOrderDivisionRecordEntity;
import com.stx.jeepay.core.expection.BizException;
import com.stx.jeepay.core.expection.ResponseException;
import com.stx.jeepay.core.service.PayOrderDivisionRecordService;
import com.stx.jeepay.core.utils.SpringBeansUtil;
import com.stx.jeepay.payment.channel.AbstractDivisionRecordChannelNotifyService;
import com.stx.jeepay.payment.model.MchAppConfigContext;
import com.stx.jeepay.payment.rqrs.msg.ChannelRetMsg;
import com.stx.jeepay.payment.rqrs.msg.DivisionChannelNotifyModel;
import com.stx.jeepay.payment.service.ConfigContextQueryService;
import com.stx.jeepay.payment.service.PayOrderProcessService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 分账渠道侧的通知入口Controller
 */
@Slf4j
@Controller
public class DivisionRecordChannelNotifyController extends AbstractCtrl {

    @Autowired
    private PayOrderDivisionRecordService payOrderDivisionRecordService;
    @Autowired
    private ConfigContextQueryService configContextQueryService;
    @Autowired
    private PayOrderProcessService payOrderProcessService;

    /**
     * 异步回调入口
     **/
    @ResponseBody
    @RequestMapping(value = {"/api/divisionRecordChannelNotify/{ifCode}"})
    public ResponseEntity doNotify(HttpServletRequest request, @PathVariable("ifCode") String ifCode) {
        String divisionBatchId = null;
        String logPrefix = "进入[" + ifCode + "]分账回调";
        log.info("===== {} =====", logPrefix);

        try {
            // 参数错误
            if (StringUtils.isEmpty(ifCode)) {
                return ResponseEntity.badRequest().body("ifCode is empty");
            }

            // 查询支付接口是否存在
            AbstractDivisionRecordChannelNotifyService divisionNotifyService =
                    SpringBeansUtil.getBean(ifCode + "DivisionRecordChannelNotifyService", AbstractDivisionRecordChannelNotifyService.class);

            // 支付通道接口实现不存在
            if (divisionNotifyService == null) {
                log.error("{}, interface not exists ", logPrefix);
                return ResponseEntity.badRequest().body("[" + ifCode + "] interface not exists");
            }

            // 解析批次号 和 请求参数
            MutablePair<String, Object> mutablePair = divisionNotifyService.parseParams(request);
            if (mutablePair == null) {
                // 数据解析失败 响应处理
                log.error("{}, mutablePair is null ", logPrefix);
                throw new BizException("解析数据异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            // 解析到订单号
            divisionBatchId = mutablePair.left;
            log.info("{}, 解析数据为：divisionBatchId:{}, params:{}", logPrefix, divisionBatchId, mutablePair.getRight());

            // 通过 batchId 查询出列表（ 注意：  需要按照ID 排序！！！！ ）
            List<PayOrderDivisionRecordEntity> recordList = payOrderDivisionRecordService.list(new LambdaQueryWrapper<PayOrderDivisionRecordEntity>()
                    .eq(PayOrderDivisionRecordEntity::getState, PayOrderDivisionRecordEntity.STATE_ACCEPT)
                    .eq(PayOrderDivisionRecordEntity::getBatchOrderId, divisionBatchId)
                    .orderByDesc(PayOrderDivisionRecordEntity::getRecordId));

            // 订单不存在
            if (recordList == null || recordList.isEmpty()) {
                log.error("{}, 待处理订单不存在. divisionBatchId={} ", logPrefix, divisionBatchId);
                return divisionNotifyService.doNotifyOrderNotExists(request);
            }

            //查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext =
                    configContextQueryService.queryMchInfoAndAppInfo(recordList.get(0).getMchNo(), recordList.get(0).getAppId());

            // 调起接口的回调判断
            DivisionChannelNotifyModel notifyResult =
                    divisionNotifyService.doNotify(request, mutablePair.getRight(), recordList, mchAppConfigContext);

            // 返回null 表明出现异常， 无需处理通知下游等操作。
            if (notifyResult == null || notifyResult.getApiRes() == null) {
                log.error("{}, 处理回调事件异常  notifyResult data error, notifyResult ={} ", logPrefix, notifyResult);
                throw new BizException("处理回调事件异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            if (notifyResult.getRecordResultMap() != null && !notifyResult.getRecordResultMap().isEmpty()) {
                for (Long divisionId : notifyResult.getRecordResultMap().keySet()) {
                    // 单条结果
                    ChannelRetMsg retMsgItem = notifyResult.getRecordResultMap().get(divisionId);

                    if (ChannelRetMsg.ChannelState.CONFIRM_SUCCESS == retMsgItem.getChannelState()) {
                        // 明确成功
                        payOrderDivisionRecordService.updateRecordSuccessOrFailBySingleItem(divisionId, PayOrderDivisionRecordEntity.STATE_SUCCESS, retMsgItem.getChannelOriginResponse());
                    } else if (ChannelRetMsg.ChannelState.CONFIRM_FAIL == retMsgItem.getChannelState()) {
                        // 明确失败
                        payOrderDivisionRecordService.updateRecordSuccessOrFailBySingleItem(
                                divisionId,
                                PayOrderDivisionRecordEntity.STATE_FAIL,
                                StringUtils.defaultIfEmpty(retMsgItem.getChannelErrMsg(), retMsgItem.getChannelOriginResponse()));
                    }
                }
            }
            log.info("===== {}, 通知完成。 divisionBatchId={}, parseState = {} =====", logPrefix, divisionBatchId, notifyResult);
            return notifyResult.getApiRes();
        } catch (BizException e) {
            log.error("{}, divisionBatchId={}, BizException", logPrefix, divisionBatchId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        } catch (ResponseException e) {
            log.error("{}, divisionBatchId={}, ResponseException", logPrefix, divisionBatchId, e);
            return e.getResponseEntity();
        } catch (Exception e) {
            log.error("{}, divisionBatchId={}, 系统异常", logPrefix, divisionBatchId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }
}
